using System;
using System.IO;
using System.DirectoryServices;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Web.Security;
using System.Data;
using System.Data.SqlClient;
using System.Security.Principal;
using System.Runtime.InteropServices;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.WebControls;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Security.AccessControl;

namespace EAT.Common
{
    //
    // Helper classes for provisioning new sites.
    //

    public class Provision
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern int RevertToSelf();

        public bool IsUrlAvailable(
                        string URL
                        )
        {
            string LookupUrl;
            SqlManager SqlM = new SqlManager();

            SqlDataReader reader = SqlM.GetReader(
                                     "SiteProvision",
                                     "SiteURL",
                                     URL
                                     );


            if (reader != null)
            {
                //
                // Check and see if the URL is already approved or pending.
                //

                while (reader.Read())
                {
                    if ((reader["Status"].ToString().Trim() == "Pending") || (reader["Status"].ToString().Trim() == "Approved"))
                    {
                        return false;
                    }
                }

                //
                // Status must equal "Denied".
                // Allow the request.
                //
                return true;
            }
            else
            {
                return true;
            }
        }
    }

    public class SPHelper
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern int RevertToSelf();
        
        public bool UserIsInRole(
                        string RoleName
                        )
        {
            //
            // The default is to check against the current site hierarchy level
            //
            SPWeb web = SPContext.Current.Web;
            return UserIsInRole(RoleName, web);
        }

        public bool UserIsInRole(
                        string RoleName, 
                        SPWeb web
                        )
        {
            SPRoleDefinition roleDef = web.RoleDefinitions[RoleName];
            if (web.AllRolesForCurrentUser.Contains(
                    roleDef
                    ))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool IsAdmin()
        {
            SPWeb web = SPContext.Current.Web;
            return IsAdmin(web);
        }

        public bool IsAdmin(SPWeb web)
        {
            //
            // This tests if the user is in a role definition that has full control
            // permissions.
            //
            foreach (SPRoleDefinition r in web.AllRolesForCurrentUser)
            {
                if ((r.BasePermissions & SPBasePermissions.FullMask) == SPBasePermissions.FullMask)
                {
                    return true;
                }
            }
            return false;
        }

        public bool IsAppAdmin()
        {
            bool b;
            SPWebApplication spwebapp = SPControl.GetContextWebApplication(HttpContext.Current);
            using (SPSite site = spwebapp.Sites[0])
            {
                using (SPWeb web = site.RootWeb)
                {
                    b = IsAdmin(web);
                }
            }
            return b;
        }

        public
        SPGroup
        AddGroup(
            SPWeb SiteWeb,
            SPUser OwnerUser,
            string GroupName,
            string GroupDescription,
            SPRoleType RoleType
            )
        {
            SPGroup Group = null;
            SPRoleAssignment RoleAssignment = null;
            SPRoleDefinition RoleDefinition = null;

            SiteWeb.SiteGroups.Add(
                                   GroupName,
                                   OwnerUser,
                                   null,
                                   GroupDescription
                                   );
            SiteWeb.Update();

            Group = SiteWeb.SiteGroups[GroupName];
            RoleAssignment = new SPRoleAssignment(Group);

            //
            // Find the role definition with the passed type.
            //
            foreach (SPRoleDefinition r in SiteWeb.RoleDefinitions)
            {
                if (r.Type == RoleType)
                {
                    RoleDefinition = r;
                    break;
                }
            }

            if (RoleDefinition == null)
            {
                throw new Exception(Resources.cantFindRoleDefinitionExceptionText);
            }

            RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
            SiteWeb.RoleAssignments.Add(RoleAssignment);

            return Group;
        }

        //
        // CreateCollaborationSite
        // Arguments:
        //      RelativeUrl - the server relative URL of the site.
        //      Title - the site title.
        //      Description - the site description.
        //      User - SPUser object representing the user who is creating
        //             or requested the site.  This user will
        //             be listed as the owner of the site.
        //      TemplateName - the name of the template to be used for the new site.
        //
        // Description:
        //      This routine creates the site and the correct cross site groups.
        //

        public bool 
        CreateCollaborationSite(
            string RelativeUrl,
            string Title,
            string Description,
            SPUser User,
            string TemplateName
            )
        {
            SPWeb Web = null;
            SPSite Site = null;
            SPWeb SiteWeb = null;
            SPWebApplication WebApp = null;
            
            bool bReverted = false;
            WindowsIdentity wi = null;
            string DisplayGroups = null;
            SPGroup Group;
            bool bSuccess = true;

            Web = SPControl.GetContextWeb(System.Web.HttpContext.Current);
            WebApp = SPWebApplication.Lookup(new Uri(Web.Url));
            
            wi = WindowsIdentity.GetCurrent();

            try
            {
                RevertToSelf();
                bReverted = true;
                WindowsIdentity.GetCurrent().Impersonate();

                //
                // Create the new site collection.
                //

                Site = WebApp.Sites.Add(
                                        RelativeUrl,
                                        Title,
                                        Description,
                                        SPContext.Current.Web.Language,
                                        TemplateName,
                                        User.LoginName,
                                        User.Name,
                                        User.Email
                                        );

                SiteWeb = Site.OpenWeb();
                SPUser OwnerUser = SiteWeb.AllUsers[0];

                //
                // Add 3 basic groups.
                //

                Group = AddGroup(
                            SiteWeb,
                            OwnerUser,
                            Resources.ownersGroupNameText,
                            Resources.ownersGroupDescriptionText,
                            SPRoleType.Administrator
                            );

                DisplayGroups += Group.ID.ToString() + ";";
                SiteWeb.Properties["vti_associateownergroup"] = Group.ID.ToString();
                SiteWeb.Properties.Update();

                Group = AddGroup(
                            SiteWeb,
                            OwnerUser,
                            Resources.membersGroupNameText,
                            Resources.membersGroupDescriptionText,
                            SPRoleType.Contributor
                            );

                DisplayGroups += Group.ID.ToString() + ";";
                SiteWeb.Properties["vti_associatemembergroup"] = Group.ID.ToString();
                SiteWeb.Properties.Update();

                Group = AddGroup(
                            SiteWeb,
                            OwnerUser,
                            Resources.visitorsGroupNameText,
                            Resources.visitorsGroupDescriptionText,
                            SPRoleType.Reader
                            );

                DisplayGroups += Group.ID.ToString() + ";";
                SiteWeb.Properties.Update();

                //
                // The final step is to show all 3 groups on the quick launch menu
                // using the string that includes the groupIds.
                //
                SiteWeb.Properties["vti_associategroups"] = DisplayGroups;
                SiteWeb.Properties.Update();
                SiteWeb.Update();
            }
            catch (Exception e)
            {
                bSuccess = false;
            }
            finally
            {
                if (bReverted && wi != null)
                {
                    wi.Impersonate();
                }
                Site.Dispose();
                SiteWeb.Dispose();
            }
            return bSuccess;
        }
    }

    public class SqlManager
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        static extern int RevertToSelf();

        //
        // OpenConnection
        // Arguments:
        // Description:
        //      Creates a connection to the connection string listed in the appropriate
        //      section of web.config
        //
        private SqlConnection OpenConnection()
        {
            WindowsIdentity wi         = null;
            bool            bReverted  = false;
            string          dbConn     = null;
            SqlConnection   connection = null;

            try
            {
                wi = WindowsIdentity.GetCurrent();
                RevertToSelf();
                bReverted = true;
                WindowsIdentity.GetCurrent().Impersonate();

                dbConn = ConfigurationManager.ConnectionStrings["DBConnectionString"].ConnectionString;
                connection = new SqlConnection(
                                     dbConn
                                     );
                connection.Open();
            }
            catch (Exception e)
            {
                if (connection != null)
                {
                    connection.Close();
                }
            }
            finally
            {
                if (bReverted && wi != null)
                {
                    wi.Impersonate();
                }
            }   
            return connection;
        }

        //
        // SetEntry
        // Arguments:
        //      DbName - the database to modify
        //      Column - the column to modify
        //      SetValue - the value to set
        // Description:
        //      Issues a SQL statement of the form "UPDATE DbName SET Column = SetValue"
        //
        public void SetEntry(
                        string DbName,
                        string Column,
                        string SetValue
                        )
        {
            SetEntry(
                DbName,
                Column,
                SetValue,
                null,
                null
                );
        }

        //
        // SetEntry
        // Arguments:
        //      DbName - the database to modify
        //      Column - the column to modify
        //      SetValue - the value to set
        //      Name - selector name
        //      Value - selector value
        // Description:
        //      Issues a SQL statement of the form "UPDATE DbName SET Column = SetValue WHERE Name = Value"
        //
        public void SetEntry(
                        string DbName,
                        string Column,
                        string SetValue,
                        string Name,
                        string Value
                        )
        {
            SqlConnection connection;
            SqlCommand command;

            connection = OpenConnection();

            if (Name == null || Value == null)
            {
                command = new SqlCommand(
                                     "UPDATE " + DbName + " SET " + Column + " = @Value",
                                     connection
                                     );

                command.Parameters.Add(
                                       "@Value",
                                       SqlDbType.NChar
                                       );
                command.Parameters["@Value"].Value = SetValue;
            }
            else
            {
                command = new SqlCommand(
                     "UPDATE " + DbName + " SET " + Column + " = @SetValue WHERE " + Name + " = @value",
                     connection
                     );

                command.Parameters.Add(
                                       "@SetValue",
                                       SqlDbType.NChar
                                       );
                
                command.Parameters["@SetValue"].Value = SetValue;

                command.Parameters.Add(
                                       "@value",
                                       SqlDbType.NChar
                                       );
                
                command.Parameters["@value"].Value = Value;
            }
            command.ExecuteNonQuery();
            connection.Close();
        }

        //
        // GetEntry
        // Arguments:
        //      DbName - the database to query
        //      Column - the column to retrieve
        // Description:
        //      Issues a SQL statement of the form "SELECT * FROM DbName" and returns
        //      the value of the column specified.
        //
        public string GetEntry(
                          string DbName,
                          string Column
                          )
        {
            return GetEntry(
                       DbName,
                       null,
                       null,
                       Column
                       );
        }

        //
        // GetEntry
        // Arguments:
        //      DbName - the database to query
        //      Name - name of the selector
        //      Value - condition of the selector
        //      Column - the column to retrieve
        // Description:
        //      Issues a SQL statement of the form "SELECT * FROM DbName where Name = Value" 
        //      and returns the value of the column specified.
        //
        public string GetEntry(
                  string DbName,
                  string Name,
                  string Value,
                  string Column
                  )
        {
            string retValue = null;
            WindowsIdentity wi = null;
            bool bReverted = false;
            SqlConnection connection = null;
            SqlCommand command = null;
            SqlDataReader reader = null;

            try
            {
                wi = WindowsIdentity.GetCurrent();
                RevertToSelf();
                bReverted = true;
                WindowsIdentity.GetCurrent().Impersonate();

                connection = OpenConnection();

                if (Name == null || Value == null)
                {
                    command = new SqlCommand(
                                        "select * from " + DbName,
                                        connection
                                        );
                }
                else
                {
                    command = new SqlCommand(
                                      "select * from " + DbName + " where " + Name + " = @value",
                                      connection
                                      );

                    command.Parameters.Add(
                                           "@value",
                                           SqlDbType.NChar
                                           );
                    command.Parameters["@value"].Value = Value;
                }

                reader = command.ExecuteReader();
                reader.Read();
                retValue = reader[Column].ToString().Trim();
            }
            catch (Exception e)
            {
                Value = string.Format(Resources.errorReadingSQLExceptionText, e.Message);
            }
            finally
            {
                if (bReverted && wi != null)
                {
                    wi.Impersonate();
                }
                if (connection != null)
                {
                    connection.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return retValue;
        }

        //
        // GetRows
        // Arguments:
        //      DbName - name of the database.
        //      Name - selector
        //      Value - selector value
        // Description:
        //      Issues a SQL statement of the form "SELECT * from DbName WHERE Name = Value" 
        //      and returns the rows which satisfy in the form of a DataTable.
        //
        public DataTable GetRows(
                             string DbName,
                             string Name,
                             string Value
                             )
        {
            SqlConnection connection = null;
            SqlCommand command = null;
            SqlDataReader reader = null;
            DataTable dt = null;
            DataRow dr = null;

            try
            {
                connection = OpenConnection();

                if (Name == null || Value == null)
                {
                    command = new SqlCommand(
                                        "select * from " + DbName,
                                        connection
                                        );
                }
                else
                {
                    command = new SqlCommand(
                                      "select * from " + DbName + " where " + Name + " = @value",
                                      connection
                                      );

                    command.Parameters.Add(
                                           "@value",
                                           SqlDbType.NChar
                                           );
                    command.Parameters["@value"].Value = Value;
                }

                reader = command.ExecuteReader();
                dt = new DataTable();
                while (reader.Read())
                {
                    dr = dt.NewRow();
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        dr[i] = reader[i].ToString();
                    }
                    dt.Rows.Add(dr);
                }
            }
            catch (Exception e)
            {
                Value = string.Format(Resources.errorReadingSQLExceptionText, e.Message);
            }
            finally
            {
                if (connection != null)
                {
                    connection.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return dt;
        }

        //
        // GetReader
        // Arguments:
        //      DbName - database name
        //      Name - Selector name
        //      Value - Selector Value
        // Description:
        //      Issues a SQL statement of the form "SELECT * from DbName WHERE Name = Value" and
        //      returns the reader object created by executing the SQL command.
        //
        public SqlDataReader GetReader(
                             string DbName,
                             string Name,
                             string Value
                             )
        {
            SqlConnection connection = null;
            SqlCommand command = null;
            SqlDataReader reader = null;

            try
            {
                connection = OpenConnection();

                if (Name == null || Value == null)
                {
                    command = new SqlCommand(
                                        "select * from " + DbName,
                                        connection
                                        );
                }
                else
                {
                    command = new SqlCommand(
                                      "select * from " + DbName + " where " + Name + "= @value",
                                      connection
                                      );

                    command.Parameters.Add(
                                           "@value",
                                           SqlDbType.NChar
                                           );
                    command.Parameters["@value"].Value = Value;
                }

                reader = command.ExecuteReader();
            }
            catch (Exception e)
            {
                Value = string.Format(Resources.errorReadingSQLExceptionText, e.Message);
                if (connection != null)
                {
                   connection.Close();
                }
            }
            finally
            {
            }
            return reader;
        }
    }

    public class WebPartTable
    {
        //
        // Table is the DataTable that contains information for the web part.
        //
        DataTable Table;

        //
        // SortColumn and SortOrder are parameters in postback that describe 
        // the desired sort.
        //
        string SortColumn;
        string SortOrder;

        //
        // The web part tag.
        //
        string Tag;

        public WebPartTable(string WebPartTag)
        {
            Table      = new DataTable();
            Tag        = WebPartTag;
            SortColumn = null;
            SortOrder  = null;
        }

        //
        // GetTag
        // Returns the tag for this table.
        //
        public string GetTag(
                          )
        {
            return Tag;
        }

        //
        // GetTable
        // Returns a pointer to the internal DataTable.
        //
        public DataTable GetTable(
                      )
        {
            return Table;
        }

        //
        // GetSortedRows
        // Returns a pointer to the sorted rows.
        //
        public DataRow[] GetSortedRows(
                             string filter
                             )
        {
            return Table.Select(
                             filter,
                             SortExpression()
                             );
        }

        //
        // GetSortColumn / SetSortColumn and GetSortOrder / SetSortOrder are used 
        // to modify and view the column name used for sorting the DataTable.
        //

        public string GetSortColumn(
                          )
        {
            return SortColumn;
        }

        public void SetSortColumn(
                        string NewSortColumn
                        )
        {
            SortColumn = NewSortColumn;
        }

        public string GetSortOrder(
                          )
        {
            return SortOrder;
        }

        public void SetSortOrder(
                        string NewSortOrder
                        )
        {
            SortOrder = NewSortOrder;
        }
                        
        //
        // SortExpression
        // Arguments:
        // Description:
        //      Build a string to pass to DataTable.Select describing which
        //      column to sort and in which direction.  this.SortColumn and 
        //      this.SortOrder are used for this purpose.
        //
        private string SortExpression(
                           )
        {
            string s;

            if (SortColumn == null)
            {
                return null;
            }

            s = SortColumn + " ";

            if (SortOrder == "+")
            {
                s += "ASC";
            }
            else
            {
                s += "DESC";
            }
            return s;
        }

        //
        // SortLink
        // Arguments:
        //      column - the column name to sort.
        // Description:
        //      Build a postback link that contains correct arguments for sorting
        //      the passed column.
        //
        public string SortLink(
                           string Column,
                           string LinkText
                           )
        {
            string s;

            s = @"<a href=""javascript:__doPostBack('__Page','";
            s += Tag + ",sort," + Column + ",";

            //
            // if we are generating the html for the current sorted column
            // then we must make certain that the newly loaded html sorts 
            // in the opposite direction.
            //
            if (Column == SortColumn)
            {
                if (SortOrder == "+")
                {
                    s += "-";
                }
                else
                {
                    s += "+";
                }
            }
            else
            {
                s += "-";
            }
            s += @"')"" style=""color:white;"">" + LinkText + "</a>";
            return s;
        }
     
        public string SortLink(
                           string Column
                           )
        {
            return SortLink(Column, Column);
        }

        public bool IsUserInConfigGroup(
                        SPUser User,
                        string ConfigGroup
                        )   
        {
            SqlManager SqlM = new SqlManager();
            string GroupName = SqlM.GetEntry(
                                        "Config",
                                        ConfigGroup
                                        );

            foreach (SPGroup Group in User.Groups)
            {
                if (Group.Name.Equals(GroupName))
                {
                    return true;
                }
            }
            return false;
        }
    }

    public class Receiver : SPFeatureReceiver
    {
        String ownerName = "ECTSBase";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {

            string strLDAPHost = properties.Definition.Properties["LDAPHost"].Value;
            string strLDAPContainer = properties.Definition.Properties["LDAPContainer"].Value;
            string strLDAPSPort = properties.Definition.Properties["LDAPSPort"].Value;
            string strSQLServer = properties.Definition.Properties["SQLServer"].Value;
            string strSMTPHost = properties.Definition.Properties["SMTPHost"].Value;
            string strMailFrom = properties.Definition.Properties["MailFrom"].Value;

            SPWebApplication spWebApp = (SPWebApplication)properties.Feature.Parent;

            // SETUP CONFIGURATION STRINGS

            createModification(spWebApp, ownerName,
                "connectionStrings",
                "/configuration",
                "<connectionStrings />",
                10U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "add[@name=\"ADAMConnectionString\"]",
                "/configuration/connectionStrings",
                "<add name=\"ADAMConnectionString\" connectionString=\"" +
                "LDAP://" + strLDAPHost + ":" + strLDAPSPort + "/CN=Users," + strLDAPContainer + "\" />",
                20U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "add[@name=\"DBConnectionString\"]",
                "/configuration/connectionStrings",
                "<add name=\"DBConnectionString\" connectionString=\"Data Source=" + strSQLServer + "; Database=ECTS; Integrated Security=SSPI\" />",
                30U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            // SETUP MEMBERSHIP PROVIDER

            createModification(spWebApp, ownerName,
                "membership[@defaultProvider=\"ADAMUser\"]",
                "/configuration/system.web",
                "<membership defaultProvider=\"ADAMUser\" />",
                40U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "providers",
                "/configuration/system.web/membership[@defaultProvider=\"ADAMUser\"]",
                "<providers />",
                50U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "add[@name=\"ADAMUser\"]",
                "/configuration/system.web/membership[@defaultProvider=\"ADAMUser\"]/providers",
                "<clear /><add name=\"ADAMUser\" type=\"System.Web.Security.ActiveDirectoryMembershipProvider, " +
                    "System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" " +
                    "connectionStringName=\"ADAMConnectionString\" " +
                    "attributeMapUsername=\"userPrincipalName\" " +
                    "requiresQuestionAndAnswer=\"true\" " +
                    "enablePasswordReset=\"true\" " +
                    "attributeMapPasswordQuestion=\"eatmuPasswordQuestion\" " +
                    "attributeMapPasswordAnswer=\"eatmuPasswordAnswer\" " +
                    "attributeMapFailedPasswordAnswerCount=\"eatmuFPAC\" " +
                    "attributeMapFailedPasswordAnswerTime=\"eatmuFPAT\" " +
                    "attributeMapFailedPasswordAnswerLockoutTime=\"eatmuFPALT\" />",
                60U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            // SETUP FORM-BASED LOGIN

            createModification(spWebApp, ownerName,
                "forms[@loginUrl]",
                "/configuration/system.web/authentication[@mode]",
                "<forms loginUrl=\"/_layouts/ExternalCollaboration/login.aspx\" />",
                80U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            // SETUP EMAIL CONFIGURATION

            createModification(spWebApp, ownerName,
                "system.net",
                "/configuration",
                "<system.net />",
                90U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "mailSettings",
                "/configuration/system.net",
                "<mailSettings />",
                100U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "smtp",
                "/configuration/system.net/mailSettings",
                "<smtp from=\"" + strMailFrom + "\" />",
                110U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "network",
                "/configuration/system.net/mailSettings/smtp[@from=\"" + strMailFrom + "\"]",
                "<network host=\"" + strSMTPHost + "\" port=\"25\" defaultCredentials=\"true\" />",
                120U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            // SETUP PASSWORD RESET ACCESS MODIFICATION

            createModification(spWebApp, ownerName,
                "location[@path=\"_layouts/ExternalCollaboration/PasswordReset.aspx\"]",
                "/configuration",
                "<location path=\"_layouts/ExternalCollaboration/PasswordReset.aspx\" />",
                130U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "system.web",
                "/configuration/location[@path=\"_layouts/ExternalCollaboration/PasswordReset.aspx\"]",
                "<system.web />",
                140U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "authorization",
                "/configuration/location[@path=\"_layouts/ExternalCollaboration/PasswordReset.aspx\"]/system.web",
                "<authorization />",
                150U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            createModification(spWebApp, ownerName,
                "allow[@users]",
                "/configuration/location[@path=\"_layouts/ExternalCollaboration/PasswordReset.aspx\"]/system.web/authorization",
                "<allow users=\"*\" />",
                160U,
                SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            // add modifications

            spWebApp.WebService.ApplyWebConfigModifications();

        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            // Remove our web.config modifications

            SPWebApplication spWebApp = (SPWebApplication)properties.Feature.Parent;

            for (int i = spWebApp.WebConfigModifications.Count - 1; i >= 0; i--)
            {
                if (spWebApp.WebConfigModifications[i].Owner == ownerName)
                    spWebApp.WebConfigModifications.Remove(spWebApp.WebConfigModifications[i]);
            }

            spWebApp.WebService.ApplyWebConfigModifications();
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }

        private void createModification(
                                            SPWebApplication webApp,
                                            string ownerName,
                                            string Name,
                                            string XPath,
                                            string Value,
                                            uint Order,
                                            SPWebConfigModification.SPWebConfigModificationType modType
                                            )
        {
            SPWebConfigModification modification = new SPWebConfigModification();
            modification.Name = Name;
            modification.Path = XPath;
            modification.Owner = ownerName;
            modification.Sequence = Order;
            modification.Type = modType;
            modification.Value = Value;
            webApp.WebConfigModifications.Add(modification);
            return;
        }
    }
}